﻿using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;

namespace KubertSoft.MSBuildTasks.Subversion
{
    /// <summary>
    /// Base class for subversion tool based tasks.
    /// </summary>
    public abstract class SvnTaskBase : ToolTask
    {
        /// <summary>
        /// The command line based on added swithces.
        /// </summary>
        internal protected CommandLineBuilder CommandLine  { get; internal set; }

        /// <summary>
        /// The collection of input task items.
        /// </summary>
        internal protected TaskItemDictionary InputTaskItems { get; internal set; }

        /// <summary>
        /// The collection of output task items.
        /// </summary>
        internal protected TaskItemDictionary OutputTaskItems { get; internal set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="SvnTaskBase"/> class.
        /// </summary>
        protected SvnTaskBase()
        {
            CommandLine = new CommandLineBuilder();
            InputTaskItems = new TaskItemDictionary();
            OutputTaskItems = new TaskItemDictionary();
        }

        /// <summary>
        /// Runs the exectuable file with the specified task parameters.
        /// Initializes output parameters from output.
        /// </summary>
        /// <returns>
        /// <c>true</c> if the task completed successfully; <c>false</c> otherwise.
        /// </returns>
        public override bool Execute()
        {
            LogBeforeExecution();
            InitializeInputParameters();
            InputTaskItems.LogItems(Log, Properties.Resources.SvnTaskBase_InputTaskItemLoggingFormat);
            var result = ExecuteInternal();
            InitializeOutputParameters();
            OutputTaskItems.LogItems(Log, Properties.Resources.SvnTaskBase_OutputTaskItemLoggingFormat);
            LogExecutionResults();
            return result;
        }

        /// <summary>
        /// Determines where execution errors raised by the executable file should be handled.
        /// </summary>
        /// <returns>
        /// true if the method runs successfully; otherwise, false.
        /// </returns>
        protected override bool HandleTaskExecutionErrors()
        {
            return false;
        }

        /// <summary>
        /// Gets the name of the executable file to run.
        /// </summary>
        /// <returns>
        /// The name of the executable file to run.
        /// </returns>
        protected override string GenerateFullPathToTool()
        {
            return ToolName;
        }

        /// <summary>
        /// Returns a string value containing the command line arguments to pass directly to the executable file.
        /// </summary>
        /// <returns>
        /// A string value containing the command line arguments to pass directly to the executable file.
        /// </returns>
        protected override sealed string GenerateCommandLineCommands()
        {
            if (IsCommandBased)
                CommandLine.AppendSwitch(Command);
            BuildCommandLine();
            return CommandLine.ToString();
        }

        /// <summary>
        /// Gets a value indicating whether this task is command based.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is command based; otherwise, <c>false</c>.
        /// </value>
        protected virtual bool IsCommandBased
        {
            get { return true; }
        }

        /// <summary>
        /// Gets the command.
        /// </summary>
        /// <value>The command.</value>
        protected abstract string Command { get; }

        /// <summary>
        /// When overriden builds command line swithces and parameters from input task parameters.
        /// </summary>
        protected internal abstract void BuildCommandLine();

        /// <summary>
        /// Initializes input parameters.
        /// </summary>
        protected internal abstract void InitializeInputParameters();

        /// <summary>
        /// Initializes output parameters.
        /// </summary>
        protected internal abstract void InitializeOutputParameters();

        /// <summary>
        /// Executes the internal execute method.
        /// </summary>
        /// <returns></returns>
        protected virtual bool ExecuteInternal()
        {
            return base.Execute();
        }

        /// <summary>
        /// Logs before execution.
        /// </summary>
        private void LogBeforeExecution()
        {
            Log.LogMessage(MessageImportance.High, Properties.Resources.SvnTaskBase_ExecutionStarted, ExitCode);
        }

        /// <summary>
        /// Logs the success execution or not.
        /// </summary>
        private void LogExecutionResults()
        {
            if (ExitCode == 0)
                Log.LogMessage(MessageImportance.High, Properties.Resources.SvnTaskBase_ExecutionCompleted, ExitCode);
            else
                Log.LogError(Properties.Resources.SvnTaskBase_ExecutionFailed, ExitCode);
        }
    }
}
